<?php
class Log extends Object
{
	public static $disableLogSql = false;
    public static $sql = array();
    public static $vars = array();
    public static $errors = array();
    public static $sqlErrors = array();
    public static $sqlQueryTypes = array();
	public static $errorTypes = array (
		E_ERROR              => 'Error',
		E_WARNING            => 'Warning',
		E_PARSE              => 'Parsing Error',
		E_NOTICE             => 'Notice',
		E_CORE_ERROR         => 'Core Error',
		E_CORE_WARNING       => 'Core Warning',
		E_COMPILE_ERROR      => 'Compile Error',
		E_COMPILE_WARNING    => 'Compile Warning',
		E_USER_ERROR         => 'UserModel Error',
		E_USER_WARNING       => 'UserModel Warning',
		E_USER_NOTICE        => 'UserModel Notice',
		E_STRICT             => 'Runtime Notice',
        E_RECOVERABLE_ERROR  => 'Catchable fatal error'
	);

    public static function LogSql($sql, $affected, $time)
    {
    	if (self::$disableLogSql) return;

    	$sql = String::RemoveBlankline($sql);
        $sqllog['sql'] = htmlentities($sql);
        $sqllog['affected'] = $affected;
        $sqllog['time'] = $time;
        self::$sql[] = $sqllog;
    }

    public static function LogVariable($var, $label = null)
    {
    	$log['label'] = $label;
    	$log['value'] = $var;
        self::$vars[] = $log;
    }

    public static function LogError($err)
    {
        self::$errors[] = $err;
    }

    public static function LogSqlError($msg, $sql = null, $errno = null)
    {
    	$message = "$msg<br/><b>sql:</b> $sql";
	    $ex = new Exception($message);
	    $trace = $ex->getTraceAsString();
		$err['message'] = "$message<br/>$trace";
    	self::$sqlErrors[] = $err;
        self::FileLog($message, 'errors_sql', 'sql');
		throw $ex;
    }

    public static function LogQueryType($type, $table)
    {
    	if (isset(self::$sqlQueryTypes[$type]) && isset(self::$sqlQueryTypes[$type][$table]))
            $count = self::$sqlQueryTypes[$type][$table]['count'] += 1;
		else
            $count = self::$sqlQueryTypes[$type][$table]['count'] = 1;
        self::$sqlQueryTypes[$type][$table]['label'] = "$table($count)";
    }

    public static function ErrorHandler($errno, $message, $filename, $linenum, $vars)
    {
        if ($errno == E_STRICT) return;

        $err_type = array_key_exists($errno, self::$errorTypes) ? self::$errorTypes[$errno] : $errno;
        $ex = new Exception($message);
        $trace = $ex->getTraceAsString();
        $err['message'] = "<b>$err_type</b>: $message in <b>$filename</b> on line <b>$linenum</b><br/>$trace";
        self::LogError($err);

        $msgbody = "$message in $filename on line $linenum";

        self::FileLog($msgbody, 'errors', $err_type);

        if ($errno == E_RECOVERABLE_ERROR || AppConfig::GetInstance()->IsDebugMode())
            throw new Exception($msgbody);
    }

    public static function FatalHandler($buffer)
    {
		if (strpos($buffer, AppConfig::GetInstance()->SIGN_FATAL_ERROR) !== false)
		{
            self::FileLog($buffer, 'errors_fatal', 'fatal');
            $buffer = self::GetLogMessage($buffer);
            self::EmailErrorLog('Fatal error', $buffer);
            self::RedirectIfNotDebugMode();
		}
		return $buffer;
    }

    public static function ExceptionHandler($exception)
    {
        $msg = '<b>Uncaught exception:</b> '.$exception->getMessage()."\n".$exception->getTraceAsString();
        self::FileLog($msg, 'errors_exception', 'fatal');
        $msg = self::GetLogMessage($msg);
        self::EmailErrorLog('Exception', $msg);
        self::RedirectIfNotDebugMode();
        echo $msg;
    }

    public static function LogException($exception)
    {
        $err['message'] = '<b>Caught exception:</b> '.$exception->getMessage()."\n".$exception->getTraceAsString();
        self::LogError($err);
    }

    protected static function FileLog($message, $file_name, $error_type)
    {
        if (AppConfig::GetInstance()->LOG_FILE)
        {
            $header = self::GetLogHeader();
            $message = "$header [$error_type]: $message\n";

            $today = date('Y-m-d');
            error_log($message, 3, AppConfig::GetInstance()->DIR_LOGS.DS."{$file_name}_$today.log");
        }
    }

    protected static function GetLogHeader()
    {
        $time_stamp = date('Y-m-d H:i:s');
        $request_uri = $_SERVER['REQUEST_URI'];
        $ip = $_SERVER['REMOTE_ADDR'];
        return "[$time_stamp] [$ip] [$request_uri]";
    }

    protected static function GetLogMessage($msg)
    {
        $log = LogControl::GetInstance();
        $header = self::GetLogHeader();
        return "<pre>$header</pre>"
            ."<div style='margin-left:10px'><pre>$msg</pre></div>"
            .$log->RenderErrorLog()
            .$log->RenderSqlErrorLog()
            .$log->debugLog;
    }

    protected static function RedirectIfNotDebugMode()
    {
        if (!AppConfig::GetInstance()->IsDebugMode())
            RequestHandler::Redirect(AppConfig::GetInstance()->URL);
    }

    protected static function EmailErrorLog($subject, $message)
    {
        if (AppConfig::GetInstance()->LOG_EMAIL)
        {
            $today = date('Y-m-d');
            $subject = '['.APP_NAME." error] $subject - $today";
            $header = "MIME-Version: 1.0\nContent-type: text/html; charset=iso-8859-1";
            mail(AppConfig::GetInstance()->EMAIL_DEBUG, $subject, $message, $header);
        }
    }

    public static function EmailLog($subject, $message)
    {
        $today = date('Y-m-d');
        $subject = '['.AppConfig::GetInstance()->APP_NAME." log] $subject - $today";
        $header = "MIME-Version: 1.0\nContent-type: text/html; charset=iso-8859-1";
        mail(AppConfig::GetInstance()->EMAIL_DEBUG, $subject, $message, $header);
    }

    public static function ToFile($var, $label = null)
    {
        $msg = print_r($var, true);
        self::FileLog($msg, 'debug.log', 'debug');
    }
}
?>
